﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using winAppGame.model;
using winAppGame.service;

namespace winAppGame.service.rulechecker
{
    /// <summary>
    /// author:zuowenjun
    /// copyright:www.zuowenjun.cn
    /// 4带2、4带2的顺子出牌规则检查器
    /// </summary>
    public class FourWithDoublePaiRuleChecker : PaiRuleChecker
    {
        public override int ForBaseCount => 6;

        public override int ForIncrementCount => 6;

        public override List<PaiRuleType.PaiRuleTypeItem> ForRuleTypes => BuildPaiRuleTypeItems(PaiRuleType.FourWithDouble, PaiRuleType.FourWithDoubleMore);

        protected override PaiRuleCheckResult DoCheckAllowShowPais(List<Pai> selectedPais, List<Pai> lastShowPais, PaiRuleCheckContext checkContext)
        {
            var compare = ComparePais(selectedPais, lastShowPais, 4);

            if (compare > 0)
            {
                return PaiRuleCheckResult.Pass(checkContext.SelectedRuleType);
            }

            return PaiRuleCheckResult.Failed("出牌数值<=上家已出牌数值！");
        }

        protected override PaiRuleCheckResult DoCheckSelectedPais(List<Pai> selectedPais, PaiRuleCheckContext checkContext)
        {
            var groupDic = ConvertToDictionary(selectedPais);
            int fourPaiCount = groupDic.Where(p => p.Value == 4).Count();
            int doublePaiCount = groupDic.Where(p => p.Value == 2).Count();

            if (fourPaiCount != doublePaiCount)
            {
                return PaiRuleCheckResult.Failed("出牌张数不正确，4带2必需至少6张或6的倍数张！");
            }

            if (selectedPais.Count != fourPaiCount * 4 + doublePaiCount * 2)
            {
                return PaiRuleCheckResult.Failed("出牌张数不正确，3带2必需至少5张或5的倍数张！");
            }

            var fourPaiValues = groupDic.Where(p => p.Value == 4).Select(p => p.Key).ToList();

            if (!IsSerial(fourPaiValues))
            {
                return PaiRuleCheckResult.Failed("出牌规则不正确，多个4带2必需每个4张牌数值是连续的！");
            }

            checkContext.SelectedRuleType = fourPaiCount > 1 ? PaiRuleType.FourWithDoubleMore : PaiRuleType.FourWithDouble;
            return PaiRuleCheckResult.Pass(checkContext.SelectedRuleType);
        }


        public override PaiRuleCheckResult AutoSelectPais(IDictionary<Pai, int> groupPais, IEnumerable<Pai> lastShowPais, PaiRuleType.PaiRuleTypeItem showRuleType)
        {
            var fourGroupPais = groupPais.Where(kv => kv.Value == 4).OrderBy(kv => kv.Key).Select(kv => kv);
            //排除掉已选4个的牌
            var remainderGroupPais = groupPais.Except(fourGroupPais, new LambdaEqualityComparer<KeyValuePair<Pai, int>>((x, y) => x.Key == y.Key));

            var doubleGroupPais = remainderGroupPais.Where(kv => kv.Value >= 2).OrderBy(kv => kv.Key).Select(kv => kv);

            if (lastShowPais.HasItem())
            {
                var lastShowFourPais = ConvertToDictionary(lastShowPais).Where(kv => kv.Value == 4).AsEnumerable();
                var lastShowMinPai = lastShowFourPais.Min(kv => kv.Key);
                fourGroupPais = fourGroupPais.Where(kv => kv.Key > lastShowMinPai).OrderBy(kv => kv.Key).Select(kv => kv);
                return DoAutoSelectPais(fourGroupPais, doubleGroupPais, lastShowFourPais, showRuleType);
            }
            else
            {
                return DoAutoSelectPais(fourGroupPais, doubleGroupPais, null, showRuleType);
            }
        }

        private PaiRuleCheckResult DoAutoSelectPais(IEnumerable<KeyValuePair<Pai, int>> fourGroupPais, IEnumerable<KeyValuePair<Pai, int>> doubleGroupPais, IEnumerable<KeyValuePair<Pai, int>> lastShowFourPais, PaiRuleType.PaiRuleTypeItem showRuleType)
        {
            if (!fourGroupPais.HasItem() || !doubleGroupPais.HasItem())
            {
                return PaiRuleCheckResult.Failed("要不起！");
            }

            Pai prePai = null;
            int forIndex = 0;
            Dictionary<Pai, int> okPais = new Dictionary<Pai, int>();
            int lowShowPaisCount = lastShowFourPais.HasItem() ? lastShowFourPais.Count() : 2;

            foreach (var kv in fourGroupPais)
            {
                forIndex++;
                if (showRuleType == PaiRuleType.FourWithDouble)
                {
                    var selectedDoubleGroupPai = doubleGroupPais.OrderBy(p => p.Value).First();
                    okPais[kv.Key] = kv.Value;
                    okPais[selectedDoubleGroupPai.Key] = 2;
                    return PaiRuleCheckResult.Pass(PaiRuleType.FourWithDouble, okPais);
                }

                if (prePai != null)
                {
                    if (prePai + 1 != kv.Key)
                    {
                        if (forIndex >= fourGroupPais.Count() || forIndex > lowShowPaisCount)
                        {
                            //若最后一张牌 或 已达到连续2个4张及以上，则中止
                            break;
                        }
                        //否则重置，重新检测连续
                        okPais.Clear();
                        forIndex = 1;
                    }
                    else if (lastShowFourPais.HasItem() && okPais.Count() == lastShowFourPais.Count())
                    {
                        //若满足上家出牌张数则中止
                        break;
                    }
                }

                prePai = kv.Key;
                okPais.Add(kv.Key, kv.Value);
            }

            if (okPais.Count() < lowShowPaisCount || okPais.Count() < doubleGroupPais.Count())
            {
                //如果4张的小于2个连续 或 4张的连续个数<对子的连续个数，则说明无法构成4+4+N+2+N的出牌规则
                return PaiRuleCheckResult.Failed("要不起！");
            }

            //选择对应个数的对子的牌添加到出牌集合中okPais
            var selectedDoubleGroupPais = doubleGroupPais.Take(okPais.Count());
            foreach (var kv in selectedDoubleGroupPais)
            {
                okPais[kv.Key] = 2;
            }

            return PaiRuleCheckResult.Pass(PaiRuleType.FourWithDoubleMore, okPais);

        }
    }
}
